import logging
import threading
from event import TransportEvent, Event, Handler
from byte_buffer import ByteBuffer
from transport import Transport
from error import InactiveCloseError, ConnectionStateError

log = logging


class BufferEvent(TransportEvent):
    def __init__(self, identity, transport, etype, handler, persistent, buffer):
        super().__init__(identity, transport, etype, handler, persistent)
        self.__buffer = ByteBuffer() if buffer is None else buffer
        #TODO: self.__lock = threading.Lock()


    def buffer(self):
        return self.__buffer

    def set_buffer(self, buffer):
        if self.__buffer != buffer:
            self.__buffer = buffer
        return self

        
    def __str__(self):
        return super().__str__() + ", buffer:[{}]".format(self.__buffer)


class BufferReadEvent(BufferEvent):
    def __init__(self, identity, transport, handler, buffer):
        super().__init__(identity, transport, Event.Type.Readable, handler, True, buffer)

    def call_handler(self):
        try:
            data = self.transport().recv(1024) #TODO: 1024 
            bytes_len = self.buffer().write_bytes(data)
            log.debug(f"Recv from socket & write bytes into buffer, bytes_len:{bytes_len},bytes:{data}")

            print("BufferReadEvent:after read callback, buffer:{}".format(self.buffer()))
            if self.handler() is not None:
                return self.handler().call(self)
            return None

        except InactiveCloseError:
            log.error("remote peer is disconnected, transport:{}".format(self.transport()))
        except ConnectionStateError:
            log.error("transport not connected when readable handler is callbacked")


class BufferWriteEvent(BufferEvent):
    def __init__(self, identity, transport, handler, buffer):
        super().__init__(identity, transport, Event.Type.Writable, handler, False, buffer)


    def call_handler(self):
        try:
            if self.buffer().is_readable():
                #send_bytes = self.transport().send(self.buffer().slice())
                send_bytes = self.transport().send(self.buffer().memoryview())
                print("send_bytes:{}, readable_bytes:{}".format(send_bytes, self.buffer().readable_bytes()))
                if send_bytes > 0:
                    self.buffer().skip_bytes(send_bytes)
            else:
                pass #no data in buffer to be send

            print("BufferWriteEvent:after write callback, buffer:{}".format(self.buffer()))

            if self.handler() is not None:
                return self.handler().call(self) # if buffer_has_bytes -> register write_event;
            return None
        except InactiveCloseError:
            log.error("remote peer is disconnected, transport:{}".format(self.transport()))
        except ConnectionStateError :
            log.error("transport not connected when writeable handler is callbacked")


